package io.dy.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author dmj
 * @date 2024年04月19日 下午5:26
 * 错误消费信息之后 把信息转到错误队列
 *
 * 背景
 *  消费者消费消息 消费出现异常 开启本地重试机制(比如重试3次) 重试后还是报错 则需要有MessageRecovery接口来处理，它包含三种不同的实现
 *      1、RejectAndDontRequeueRecoverer：重试耗尽后，直接reject，丢弃消息。默认就是这种方式
 *      2、ImmediateRequeueMessageRecoverer：重试耗尽后，返回nack，消息重新入队
 *      3、RepublishMessageRecoverer：重试耗尽后，将失败消息投递到指定的交换机(推荐使用)
 *
 *  配置第3种处理方式
 */
@Configuration
public class ErrorConsumeMessageConfig {

    /**
     * 错误信息对应交换机
     */
    @Bean
    public TopicExchange errorTopicExchange(){
        return ExchangeBuilder.topicExchange("dy.error.exchange").durable(true).build();
    }

    /**
     * 错误队列
     */
    @Bean
    public Queue errorQueue(){
        return QueueBuilder.durable("dy.error.queue").build();
    }

    /**
     * 绑定
     */
    @Bean
    public Binding bindErrorExchangeAndQueue(){
        return BindingBuilder.bind(errorQueue()).to(errorTopicExchange()).with("error");
    }

    /**
     *  创建 RepublishMessageRecoverer
     */
    @Bean
    public MessageRecoverer republishMessageRecoverer(RabbitTemplate rabbitTemplate){
        return new RepublishMessageRecoverer(rabbitTemplate, "dy.error.exchange", "error");
    }
}
